//! Windows 下的键盘驱动实现
//!
//! 工作流程如下所示：
//!
//! ```text
//! KeyCode（模块统一定义） -> VirtualKey -> ScanCoed
//! ```
//!
//! - [`KeyCode`] 是统一的规范，表示一种物理上的键。
//! - [`VIRTUAL_KEY`] 由 Windows 系统定义，表示虚拟按键。
//! - [`ScanCode`] 由 Windows 系统定义，表示键盘上扫描到的按键。

use std::mem::size_of;

use windows::Win32::UI::Input::KeyboardAndMouse::{
    MapVirtualKeyW, SendInput, INPUT, INPUT_0, INPUT_KEYBOARD, KEYBDINPUT, KEYBD_EVENT_FLAGS,
    KEYEVENTF_KEYUP, KEYEVENTF_SCANCODE, MAPVK_VK_TO_VSC, VIRTUAL_KEY, VK_0, VK_1, VK_2, VK_3,
    VK_4, VK_5, VK_6, VK_7, VK_8, VK_9, VK_A, VK_ADD, VK_B, VK_BACK, VK_BROWSER_BACK,
    VK_BROWSER_FAVORITES, VK_BROWSER_FORWARD, VK_BROWSER_HOME, VK_BROWSER_REFRESH,
    VK_BROWSER_SEARCH, VK_BROWSER_STOP, VK_C, VK_CAPITAL, VK_CONVERT, VK_D, VK_DECIMAL, VK_DELETE,
    VK_DIVIDE, VK_DOWN, VK_E, VK_END, VK_ESCAPE, VK_F, VK_F1, VK_F10, VK_F11, VK_F12, VK_F13,
    VK_F14, VK_F15, VK_F16, VK_F17, VK_F18, VK_F19, VK_F2, VK_F20, VK_F21, VK_F22, VK_F23, VK_F24,
    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_G, VK_H, VK_HANGEUL, VK_HANJA, VK_HELP,
    VK_HOME, VK_I, VK_INSERT, VK_J, VK_K, VK_KANA, VK_L, VK_LAUNCH_APP1, VK_LAUNCH_APP2,
    VK_LAUNCH_MAIL, VK_LAUNCH_MEDIA_SELECT, VK_LCONTROL, VK_LEFT, VK_LMENU, VK_LSHIFT, VK_LWIN,
    VK_M, VK_MEDIA_NEXT_TRACK, VK_MEDIA_PLAY_PAUSE, VK_MEDIA_PREV_TRACK, VK_MEDIA_STOP,
    VK_MULTIPLY, VK_N, VK_NEXT, VK_NONCONVERT, VK_NUMLOCK, VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2,
    VK_NUMPAD3, VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_O,
    VK_OEM_1, VK_OEM_102, VK_OEM_2, VK_OEM_3, VK_OEM_4, VK_OEM_5, VK_OEM_6, VK_OEM_7, VK_OEM_COMMA,
    VK_OEM_MINUS, VK_OEM_PERIOD, VK_OEM_PLUS, VK_P, VK_PAUSE, VK_PRIOR, VK_Q, VK_R, VK_RCONTROL,
    VK_RETURN, VK_RIGHT, VK_RMENU, VK_RSHIFT, VK_RWIN, VK_S, VK_SCROLL, VK_SELECT, VK_SLEEP,
    VK_SNAPSHOT, VK_SPACE, VK_SUBTRACT, VK_T, VK_TAB, VK_U, VK_UP, VK_V, VK_VOLUME_DOWN,
    VK_VOLUME_MUTE, VK_VOLUME_UP, VK_W, VK_X, VK_Y, VK_Z,
};

use super::{key_code::KeyCode, KeyboardDriver, KeyboardDriverFunctions};

type ScanCode = u16;

impl KeyboardDriverFunctions for KeyboardDriver {
    /// 按下按键
    fn key_down(&self, key_code: KeyCode) {
        keybd_event(KEYEVENTF_SCANCODE, VIRTUAL_KEY(0), key_code.into());
    }

    /// 释放按键
    fn key_up(&self, key_code: KeyCode) {
        keybd_event(
            KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP,
            VIRTUAL_KEY(0),
            key_code.into(),
        );
    }
}

impl Into<ScanCode> for KeyCode {
    /// 转换成扫描码
    fn into(self) -> ScanCode {
        match self.into() {
            VIRTUAL_KEY(0) => 0,
            VIRTUAL_KEY(vk) => unsafe { MapVirtualKeyW(vk as u32, MAPVK_VK_TO_VSC) as ScanCode },
        }
    }
}

impl Into<VIRTUAL_KEY> for KeyCode {
    /// 转换成虚拟键码
    fn into(self) -> VIRTUAL_KEY {
        match self {
            KeyCode::Backspace => VK_BACK,
            KeyCode::Tab => VK_TAB,
            KeyCode::Enter | KeyCode::NumpadEnter => VK_RETURN,
            KeyCode::Pause => VK_PAUSE,
            KeyCode::CapsLock => VK_CAPITAL,
            KeyCode::KanaMode => VK_KANA,
            KeyCode::Lang1 => VK_HANGEUL,
            KeyCode::Lang2 => VK_HANJA,
            KeyCode::Escape => VK_ESCAPE,
            KeyCode::Convert => VK_CONVERT,
            KeyCode::NonConvert => VK_NONCONVERT,
            KeyCode::Space => VK_SPACE,
            KeyCode::PageUp => VK_PRIOR,
            KeyCode::PageDown => VK_NEXT,
            KeyCode::End => VK_END,
            KeyCode::Home => VK_HOME,
            KeyCode::ArrowLeft => VK_LEFT,
            KeyCode::ArrowUp => VK_UP,
            KeyCode::ArrowRight => VK_RIGHT,
            KeyCode::ArrowDown => VK_DOWN,
            KeyCode::Select => VK_SELECT,
            KeyCode::PrintScreen => VK_SNAPSHOT,
            KeyCode::Insert => VK_INSERT,
            KeyCode::Delete => VK_DELETE,
            KeyCode::Help => VK_HELP,
            KeyCode::Digit0 => VK_0,
            KeyCode::Digit1 => VK_1,
            KeyCode::Digit2 => VK_2,
            KeyCode::Digit3 => VK_3,
            KeyCode::Digit4 => VK_4,
            KeyCode::Digit5 => VK_5,
            KeyCode::Digit6 => VK_6,
            KeyCode::Digit7 => VK_7,
            KeyCode::Digit8 => VK_8,
            KeyCode::Digit9 => VK_9,
            KeyCode::KeyA => VK_A,
            KeyCode::KeyB => VK_B,
            KeyCode::KeyC => VK_C,
            KeyCode::KeyD => VK_D,
            KeyCode::KeyE => VK_E,
            KeyCode::KeyF => VK_F,
            KeyCode::KeyG => VK_G,
            KeyCode::KeyH => VK_H,
            KeyCode::KeyI => VK_I,
            KeyCode::KeyJ => VK_J,
            KeyCode::KeyK => VK_K,
            KeyCode::KeyL => VK_L,
            KeyCode::KeyM => VK_M,
            KeyCode::KeyN => VK_N,
            KeyCode::KeyO => VK_O,
            KeyCode::KeyP => VK_P,
            KeyCode::KeyQ => VK_Q,
            KeyCode::KeyR => VK_R,
            KeyCode::KeyS => VK_S,
            KeyCode::KeyT => VK_T,
            KeyCode::KeyU => VK_U,
            KeyCode::KeyV => VK_V,
            KeyCode::KeyW => VK_W,
            KeyCode::KeyX => VK_X,
            KeyCode::KeyY => VK_Y,
            KeyCode::KeyZ => VK_Z,
            KeyCode::SuperLeft => VK_LWIN,
            KeyCode::SuperRight => VK_RWIN,
            KeyCode::Sleep => VK_SLEEP,
            KeyCode::Numpad0 => VK_NUMPAD0,
            KeyCode::Numpad1 => VK_NUMPAD1,
            KeyCode::Numpad2 => VK_NUMPAD2,
            KeyCode::Numpad3 => VK_NUMPAD3,
            KeyCode::Numpad4 => VK_NUMPAD4,
            KeyCode::Numpad5 => VK_NUMPAD5,
            KeyCode::Numpad6 => VK_NUMPAD6,
            KeyCode::Numpad7 => VK_NUMPAD7,
            KeyCode::Numpad8 => VK_NUMPAD8,
            KeyCode::Numpad9 => VK_NUMPAD9,
            KeyCode::NumpadMultiply | KeyCode::NumpadStar => VK_MULTIPLY,
            KeyCode::NumpadAdd => VK_ADD,
            KeyCode::NumpadSubtract => VK_SUBTRACT,
            KeyCode::NumpadDecimal => VK_DECIMAL,
            KeyCode::NumpadDivide => VK_DIVIDE,
            KeyCode::F1 => VK_F1,
            KeyCode::F2 => VK_F2,
            KeyCode::F3 => VK_F3,
            KeyCode::F4 => VK_F4,
            KeyCode::F5 => VK_F5,
            KeyCode::F6 => VK_F6,
            KeyCode::F7 => VK_F7,
            KeyCode::F8 => VK_F8,
            KeyCode::F9 => VK_F9,
            KeyCode::F10 => VK_F10,
            KeyCode::F11 => VK_F11,
            KeyCode::F12 => VK_F12,
            KeyCode::F13 => VK_F13,
            KeyCode::F14 => VK_F14,
            KeyCode::F15 => VK_F15,
            KeyCode::F16 => VK_F16,
            KeyCode::F17 => VK_F17,
            KeyCode::F18 => VK_F18,
            KeyCode::F19 => VK_F19,
            KeyCode::F20 => VK_F20,
            KeyCode::F21 => VK_F21,
            KeyCode::F22 => VK_F22,
            KeyCode::F23 => VK_F23,
            KeyCode::F24 => VK_F24,
            KeyCode::NumLock | KeyCode::NumpadClear => VK_NUMLOCK,
            KeyCode::ScrollLock => VK_SCROLL,
            KeyCode::ShiftLeft => VK_LSHIFT,
            KeyCode::ShiftRight => VK_RSHIFT,
            KeyCode::ControlLeft => VK_LCONTROL,
            KeyCode::ControlRight => VK_RCONTROL,
            KeyCode::AltLeft => VK_LMENU,
            KeyCode::AltRight => VK_RMENU,
            KeyCode::BrowserBack => VK_BROWSER_BACK,
            KeyCode::BrowserForward => VK_BROWSER_FORWARD,
            KeyCode::BrowserRefresh => VK_BROWSER_REFRESH,
            KeyCode::BrowserStop => VK_BROWSER_STOP,
            KeyCode::BrowserSearch => VK_BROWSER_SEARCH,
            KeyCode::BrowserFavorites => VK_BROWSER_FAVORITES,
            KeyCode::BrowserHome => VK_BROWSER_HOME,
            KeyCode::AudioVolumeMute => VK_VOLUME_MUTE,
            KeyCode::AudioVolumeDown => VK_VOLUME_DOWN,
            KeyCode::AudioVolumeUp => VK_VOLUME_UP,
            KeyCode::MediaTrackNext => VK_MEDIA_NEXT_TRACK,
            KeyCode::MediaTrackPrevious => VK_MEDIA_PREV_TRACK,
            KeyCode::MediaStop => VK_MEDIA_STOP,
            KeyCode::MediaPlayPause => VK_MEDIA_PLAY_PAUSE,
            KeyCode::LaunchMail => VK_LAUNCH_MAIL,
            KeyCode::MediaSelect => VK_LAUNCH_MEDIA_SELECT,
            KeyCode::LaunchApp1 => VK_LAUNCH_APP1,
            KeyCode::LaunchApp2 => VK_LAUNCH_APP2,
            KeyCode::Semicolon => VK_OEM_1,
            KeyCode::Equal | KeyCode::Plus => VK_OEM_PLUS,
            KeyCode::Comma => VK_OEM_COMMA,
            KeyCode::Minus => VK_OEM_MINUS,
            KeyCode::Period => VK_OEM_PERIOD,
            KeyCode::Slash => VK_OEM_2,
            KeyCode::Backquote => VK_OEM_3,
            KeyCode::BracketLeft => VK_OEM_4,
            KeyCode::Backslash => VK_OEM_5,
            KeyCode::BracketRight => VK_OEM_6,
            KeyCode::Quote => VK_OEM_7,
            KeyCode::IntlBackslash | KeyCode::IntlRo | KeyCode::IntlYen => VK_OEM_102,
            _ => VIRTUAL_KEY(0),
        }
    }
}

/// 发送键盘事件
///
/// # 参数
///
/// * `flags` - 事件标志
/// * `vk` - 虚拟键值
/// * `scan` - 扫描码
///
/// # 示例
///
/// ```
/// keybd_event(KEYBD_EVENT_FLAGS::KEY_DOWN, VIRTUAL_KEY::VK_CONTROL, 0);
/// ```
fn keybd_event(flags: KEYBD_EVENT_FLAGS, vk: VIRTUAL_KEY, scan: u16) {
    let input = INPUT {
        r#type: INPUT_KEYBOARD,
        Anonymous: INPUT_0 {
            ki: KEYBDINPUT {
                wVk: vk,
                wScan: scan,
                dwFlags: flags,
                time: 0,
                dwExtraInfo: 0,
            },
        },
    };

    unsafe {
        SendInput(
            &[input as INPUT],
            size_of::<INPUT>()
                .try_into()
                .expect("Could not convert the size of INPUT to i32"),
        )
    };
}
